/*
  Copyright 2012 Sergey Ostanin

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

package ru.irenproject.inputQuestion;

import static ru.irenproject.it.XmlUtils.find;
import static ru.irenproject.it.XmlUtils.findBoolean;
import static ru.irenproject.it.XmlUtils.findChild;
import static ru.irenproject.it.XmlUtils.getChild;
import static ru.irenproject.it.XmlUtils.getChildren;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.w3c.dom.Element;

import ru.irenproject.Utils;
import ru.irenproject.inputQuestion.InputQuestionProtos.SpacePreprocessMode;
import ru.irenproject.it.It;
import ru.irenproject.it.ItInputException;
import ru.irenproject.it.ItReader;
import ru.irenproject.it.QuestionReader;
import ru.irenproject.store.Store;

@Singleton public final class InputQuestionReader implements QuestionReader {
  @Inject InputQuestionReader() {}

  @Override public InputQuestion read(ItReader in, Element e, Store store) {
    InputQuestion res = store.create(InputQuestion.class);
    in.readPad(findChild(e, It.ELEM_CONTENT), res.formulation());

    Element xmlPatterns = getChild(e, It.ELEM_PATTERNS);
    if (xmlPatterns != null) {
      for (Element xmlPattern : getChildren(xmlPatterns, It.ELEM_PATTERN)) {
        readPattern(xmlPattern, res);
      }
    }

    return res;
  }

  private void readPattern(Element e, InputQuestion out) {
    switch (find(e, It.ATTR_TYPE)) {
      case It.VAL_PATTERN_TYPE_TEXT: {
        readTextPattern(e, out.addTextPattern());
        break;
      }
      case It.VAL_PATTERN_TYPE_REGEXP: {
        readRegexpPattern(e, out.addRegexpPattern());
        break;
      }
      default: {
        throw new ItInputException();
      }
    }
  }

  private void readTextPattern(Element e, TextPattern out) {
    readBasePattern(e, out);
    out.setCaseSensitive(findBoolean(e, It.ATTR_CASE_SENSITIVE));

    switch (find(e, It.ATTR_SPACES)) {
      case It.VAL_PATTERN_SPACES_NORMALIZE: {
        out.setSpaceDelimited(true);
        break;
      }
      case It.VAL_PATTERN_SPACES_IGNORE: {
        out.setSpaceDelimited(false);
        break;
      }
      default: {
        throw new ItInputException();
      }
    }

    if (findBoolean(e, It.ATTR_NUMERIC_AWARE)) {
      out.setPrecision(find(e, It.ATTR_PRECISION));
    } else {
      out.clearPrecision();
    }

    out.setWildcard(findBoolean(e, It.ATTR_WILDCARD));
  }

  private void readRegexpPattern(Element e, RegexpPattern out) {
    readBasePattern(e, out);
    out.setCaseSensitive(findBoolean(e, It.ATTR_CASE_SENSITIVE));
    out.setSpacePreprocessMode(xmlToSpacePreprocessMode(find(e, It.ATTR_SPACES)));
  }

  private static SpacePreprocessMode xmlToSpacePreprocessMode(String s) {
    switch (s) {
      case It.VAL_PATTERN_SPACES_EXACT: return SpacePreprocessMode.KEEP;
      case It.VAL_PATTERN_SPACES_NORMALIZE: return SpacePreprocessMode.NORMALIZE;
      case It.VAL_PATTERN_SPACES_IGNORE: return SpacePreprocessMode.REMOVE;
    }
    throw new ItInputException();
  }

  private void readBasePattern(Element e, Pattern out) {
    out.setValue(find(e, It.ATTR_VALUE));
    out.setQualityPercent(Utils.parseNormalizedDecimal(find(e, It.ATTR_QUALITY))
        .scaleByPowerOfTen(2).intValue());
  }
}
